package main;

import java.util.ArrayList;

import com.trolltech.qt.core.QPointF;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QGraphicsLineItem;
import com.trolltech.qt.gui.QGraphicsPolygonItem;
import com.trolltech.qt.gui.QGraphicsScene;
import com.trolltech.qt.gui.QLineF;
import com.trolltech.qt.gui.QPen;
import com.trolltech.qt.gui.QPolygonF;
import com.trolltech.qt.gui.QGraphicsItem.GraphicsItemFlag;

public class QAgregateArrow extends QCustomArrow {
	
	public QAgregateArrow(QGraphicsClass parent, QGraphicsClass child, QGraphicsScene scene){
		super(parent, child, scene);
	}

	@Override
	public void display() {
		_start = getStartPoint();
		_end = getEndPoint();
		if(!middleHasMoved){
			_middle = calculateMiddlePoint();
		}
		
		// Dispose of all the lines that are already displayed
		for(QGraphicsLineItem line : lines){
			line.dispose();
		}
		lines.clear();
		
		lines.add(drawLine(_start, _middle));
		
		if(!middleHasMoved){
			if(middlePoint!=null){
				middlePoint.dispose();
			}
			middlePoint = new QGraphicsMiddlePoint(null, _scene);
			middlePoint.setPos(_middle.x()-4, _middle.y()-4);
			middlePoint.setFlag(GraphicsItemFlag.ItemIsMovable);
			middlePoint.setFlag(GraphicsItemFlag.ItemIsFocusable);
			middlePoint.show();
		}

		drawArrowHead(_end.x(),_end.y(), _middle.x(), _middle.y());
		lines.add(drawLine(_middle, _end));
	}

	@Override
	public void drawArrowHead(double px, double py, double cx, double cy) {
		// x y  represent the coordinates of the point that will be transformed
		double x,y;
		QLineF unitVector = (new QLineF(new QPointF(px, py), new QPointF(cx, cy))).unitVector();
		QLineF normalVect = ((new QLineF(new QPointF(px, py), new QPointF(cx, cy))).normalVector()).unitVector();
		
		QPointF bottom, left, right, top;
		// (x, y) is a point of the line between (cx, cy) and (px, py) that is exactly 20 units away from (px, py)
		// in the direction of (cx, cy)
		x = px + 20*unitVector.dx();
		y = py + 20*unitVector.dy();
		
		bottom = new QPointF(x,y);
		top = new QPointF(px, py);
		left = new QPointF(px+10*unitVector.dx()+6*normalVect.dx(), py+10*unitVector.dy()+6*normalVect.dy());
		right = new QPointF(px+10*unitVector.dx()-6*normalVect.dx(), py+10*unitVector.dy()-6*normalVect.dy());
		lines.add(drawLine(top, left));
		lines.add(drawLine(top, right));
		lines.add(drawLine(bottom, left));
		lines.add(drawLine(bottom, right));
		
		_end = bottom;
	}

	@Override
	protected QPointF getEndPoint() {
		// Calculate the positions on the scene of the points that need to be linked
		QPointF parentT, parentB;
		double cx, cy;
		if(_child.pos().x()<_parent.pos().x()){
			parentT = _parent.mapToScene(_parent.boundingRect().topLeft());
			parentB = _parent.mapToScene(_parent.boundingRect().bottomLeft());
		}
		else{
			parentT = _parent.mapToScene(_parent.boundingRect().topRight());
			parentB = _parent.mapToScene(_parent.boundingRect().bottomRight());
		}
		
		cx = parentB.x();
		cy = (parentB.y()+parentT.y())/2;
		
		return new QPointF(cx,cy);
	}

	@Override
	protected QPointF getStartPoint() {
		// Calculate the positions on the scene of the points that need to be linked
		QPointF childT, childB;
		double cx, cy;
		if(_child.pos().x()<_parent.pos().x()){
			childT = _child.mapToScene(_child.boundingRect().topRight());
			childB = _child.mapToScene(_child.boundingRect().bottomRight());
		}
		else{
			childT = _child.mapToScene(_child.boundingRect().topLeft());
			childB = _child.mapToScene(_child.boundingRect().bottomLeft());
		}
		
		cx = childB.x();
		cy = (childB.y()+childT.y())/2;
		
		return new QPointF(cx,cy);
	}

}
